function PromsiseAll(promises) {
  return new Promise((resolve, reject) => {
    if (!Array.isArray(promises)) {
      reject(new TypeError("args must array"));
    }
    let res = [],
      count = 0,
      length = promises.length;

    for (let i = 0; i < length; i++) {
      Promise.resolve(promises[i])
        .then((data) => {
          res[i] = data;
          count++;
        })
        .catch((err) => {
          return new Error(err);
        });

      if (count === length) {
        resolve(res);
      }
    }
  });
}

function promiseRace(promises) {
  return new Promise((resolve, reject) => {
    if (!Array.isArray(promises)) {
      return new TypeError("arg  must a array");
    }
    promises.forEach((p) => {
      Promise.resolve(p)
        .then((data) => {
          resolve(data);
        })
        .catch((err) => {
          reject(err);
        });
    });
  });
}

function promiseAllSettled(promises) {
  const FULFILLED = "fullfilled";
  const REJECTED = "reject";
  return new Promise((resolve, reject) => {
    if (!Array.isArray(promises)) {
      return reject(new TypeError("arg must array"));
    }
    let res = [],
      count = 0,
      length = promises.length;

    for (let i = 0; i < length; i++) {
      Promise.resolve(promises[i])
        .then((data) => {
          res[i] = { status: FULFILLED, data };
        })
        .catch((err) => {
          res[i] = { status: REJECTED, err };
        });
      count++;
    }
    if (count === length) {
      resolve(res);
    }
  });
}

function allSettled(promises) {
  const FULLFILLED = "fullfilled",
    REJECTED = "rejected";
  const resolveHandler = (value) => ({ status: FULLFILLED, data: value });
  const rejectHandler = (reason) => ({ status: REJECTED, data: reason });

  return new Promise((resolve, reject) => {
    if (!Array.isArray(promises)) {
    }

    Promise.all(
      promises.map((promise) => {
        Promise.resolve(promise).then(resolveHandler, rejectHandler);
      })
    );
  });
}

Promise.promiseAllSettled = promiseAllSettled;
Promise._allSettled = allSettled;

var promise1 = new Promise(function (resolve, reject) {
  setTimeout(function () {
    reject("promise1");
  }, 2000);
});

var promise2 = new Promise(function (resolve, reject) {
  setTimeout(function () {
    resolve("promise2");
  }, 3000);
});

var promise3 = Promise.resolve("promise3");

var promise4 = Promise.reject("promise4");

Promise._allSettled([promise1, promise2, promise3, promise4]).then(function (
  args
) {
  console.log(args);
  /*
    result:
    [
      {"status":"rejected","reason":"promise1"},
      {"status":"fulfilled","value":"promise2"},
      {"status":"fulfilled","value":"promise3"},
      {"status":"rejected","reason":"promise4"}
    ]*/
});
